#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>
#include "my_serialize.h"
int serialize_string(char* buffer,int offset,const char* data){
    if(buffer == NULL || data == NULL || offset<0){
        return -1;
    }
    int tmp = strlen(data)+1;
    int n = htonl(tmp);
    memcpy(buffer+offset,&n,sizeof(n));
    offset+=sizeof(n);
    memcpy(buffer+offset,data,tmp);
    return offset+tmp;
}

int unserialize_string(char* result,const char* buffer,int offset){
    if(buffer == NULL || result == NULL || offset<0){
        return -1;
    }

    int tmp = 0;
    memcpy(&tmp,buffer+offset,sizeof(tmp));
    tmp = ntohl(tmp);
    offset+=sizeof(tmp);
    memcpy(result,buffer+offset,tmp);
    return offset+tmp;
}

int serialize_arr_ch(char* buffer,int offset,const char* data,int n){
    if(buffer == NULL || data == NULL || offset<0 || n<0){
        return -1;
    }
    int tmp = htonl(n);
    memcpy(buffer+offset,&tmp,sizeof(tmp));
    offset+=sizeof(n);
    memcpy(buffer+offset,data,n);
    return offset+n;
}

int unserialize_arr_ch(char* result,int* len,const char* buffer,int offset){
    if(buffer == NULL || result == NULL || offset<0){
        return -1;
    }

    memcpy(len,buffer+offset,sizeof(int));
    *len = ntohl(*len);
    offset+=sizeof(int);
    memcpy(result,buffer+offset,*len);
    return offset+*len;
}

int serialize_char(char* buffer,int offset,char data){
    if(buffer == NULL || offset<0){
        return -1;
    }
    memcpy(buffer+offset,&data,sizeof(char));
    return offset+sizeof(char);
}

int unserialize_char(char* result,char* buffer,int offset){
    if(buffer == NULL || result == NULL || offset<0){
        return -1;
    }
    memcpy(result,buffer+offset,sizeof(char));
    return offset+sizeof(char);
}

int serialize_short(char* buffer,int offset,short data){
    if(buffer == NULL || offset<0){
        return -1;
    }
    short tmp = htons(data);
    memcpy(buffer+offset,&tmp,sizeof(short));
    return offset+sizeof(short);
}

int unserialize_short(short* result,const char* buffer,int offset){
    if(buffer == NULL || result == NULL || offset<0){
        return -1;
    }

    memcpy(result,buffer+offset,sizeof(short));
    *result = ntohs(*result);
    return offset+sizeof(short);
}

int serialize_int(char* buffer,int offset,int data){
    if(buffer == NULL || offset<0){
        return -1;
    }
    int tmp = htonl(data);
    memcpy(buffer+offset,&tmp,sizeof(int));
    return offset+sizeof(int);
}

int unserialize_int(int* result,const char* buffer,int offset){
    if(buffer == NULL || result == NULL || offset<0){
        return -1;
    }
    memcpy(result,buffer+offset,sizeof(int));
    *result = ntohl(*result);
    return offset+sizeof(int);
}

// 检查系统是大端还是小端
int check_endianness(){
    //判断大小端
    int flag = -1;
    int tmp = 0x12345678;
    //大端返回1
    if(*(short*)&tmp != 0x5678){
        return 1;
    }
    else {
        return 0;
    }
}

u_int64_t htonll(u_int64_t _netlong){
   
    if(check_endianness() == 1){
        return _netlong;
    }
    //把long从小端转为大端
    u_int32_t tmp_h = htonl(_netlong >> 32);
    u_int32_t tmp_l = htonl(_netlong << 32 >> 32);
    _netlong = 0;
    _netlong = (_netlong | tmp_h) | ((_netlong | tmp_l) << 32);
    return _netlong;
}

u_int64_t ntohll(u_int64_t _netlong){
    //判断大小端
    int flag = -1;
    int tmp = 0x12345678;
    //大端直接返回
    if(check_endianness() == 1){
        return _netlong;
    }
    //把long从大端转为小端
    u_int32_t tmp_h = ntohl(_netlong >> 32);
    u_int32_t tmp_l = ntohl(_netlong << 32 >> 32);
    _netlong = 0;
    _netlong = (_netlong | tmp_h) | ((_netlong | tmp_l) << 32);
    return _netlong;
}

int serialize_uint64_t(char* buffer,int offset,u_int64_t data){
    if(buffer == NULL || offset<0){
        return -1;
    }
    u_int64_t tmp = htonll(data);
    memcpy(buffer+offset,&tmp,sizeof(u_int64_t));
    return offset+sizeof(u_int64_t);
}

int unserialize_uint64_t(u_int64_t* result,const char* buffer,int offset){
    if(buffer == NULL || offset<0){
        return -1;
    }
    *result = ntohll(*(u_int64_t*)(buffer+offset));
    return offset+sizeof(u_int64_t);
}
